package controls;

import java.awt.Dimension;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.IOException;
import java.sql.SQLException;
import java.util.LinkedHashMap;
import java.util.Map;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SpringLayout;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;

import main.Application;
import main.SpringUtilities;
import menuaction.RunBrowserMenuAction;

import org.xml.sax.SAXException;

import tablemanager.TableManager;
import browser.filter.BrowserFilter;
import browser.filter.FilterLeaf;
import exception.queryBuilder.AliasNotFound;
import exception.queryBuilder.AttribNotFound;
import exception.queryBuilder.UndefineKeyType;
import exception.recordEdit.SuchComponentExictException;

/**
 * klasa reprezentujaca slownik. Tzn text field polaczony z przyciskiem do wyswietlaie slownika<br>
 * wymiary wysweitlanego slownika definiuje sie w XML!!!!!!!!!!!!!!
 * 
 * @author looser
 *
 */
public class VocPanel extends JPanel
{
	public static String BROWSER_H = "browserH";
	public static String BROWSER_W = "browserW";
	
	public static final String LINKED_FIELDS = "linkedFields";
	public static final String LINKED_FIELD = "linkedField";
	
	private static final long serialVersionUID = 1L;
	JTextField textField;
	JButton showVocButton;
	RunBrowserMenuAction runBrowser;
	BrowserFilter bf;
	Dimension browserDim;
	String tableName;//nazwa tabeli, ktora bedzie slownikiem
	String fieldName;//pole pobierane ze slownika
	Map<String,LinkedField> linkedFields;
	TableManager tableManager;
	public VocPanel()
	{
		super(new SpringLayout());
		initComponents();
		browserDim = new Dimension(100,100);
		linkedFields = new LinkedHashMap<String, LinkedField>();
	}
	
	public void setBrowserSize(Dimension dim)
	{
		browserDim = dim;
	}
	
	/**
	 * 
	 * @param tableName nazwa tabeli,ktora robi za slownik
	 * @param fieldName nazwa pola (jak w bazie), ktora bedzie pobierane ze slownika
	 */
	public VocPanel(String tableName,String fieldName)
	{
		super(new SpringLayout());
		this.tableName=tableName;
		this.fieldName=fieldName;
		linkedFields = new LinkedHashMap<String, LinkedField>();		
		initComponents();
		addBasicButtonAction();
		tableManager = Application.getInstance().getTableManager(tableName);
	}
	public void setTableName(String tableName)
	{
		this.tableName=tableName;
		addBasicButtonAction();
		tableManager = Application.getInstance().getTableManager(tableName);
	}
	public void setFieldName(String fieldName)
	{
		this.fieldName=fieldName;
	}
	
	public String getTableName()
	{
		return tableName;
	}
	public String getTFieldName()
	{
		return fieldName;
	}
	
	private void initComponents()
	{
		ImageIcon vocIcon = new ImageIcon("zboon_icons/vocIcon_sm.png");
		
		textField = new JTextField();
		textField.setMargin(new Insets(0,0,0,0));		
		showVocButton = new JButton(vocIcon);
		showVocButton.setFocusable(false);
		showVocButton.setMargin(new Insets(0,0,0,0));	
		/*showVocButton.addFocusListener( new FocusAdapter()
			{
				@Override
				public void focusGained(FocusEvent e)
				{				
					showVocButton.transferFocus();					
				}
			}
			);*/
		this.add(textField);
		this.add(showVocButton);
		
		SpringUtilities.makeCompactGrid(this,
				1, 2, //rows, cols
				1, 1,        //initX, initY
				1, 1);				
		runBrowser = new RunBrowserMenuAction()
		{
			@Override
			public void runMenuAction() throws AliasNotFound, SQLException, SAXException, IOException, ClassNotFoundException, InstantiationException, IllegalAccessException {
				updateFilter();
				runBrowser.setSize(browserDim);
				setLocation(textField.getLocationOnScreen());
				super.runMenuAction();
			}
		};
		textField.getDocument().addDocumentListener(new DocumentListener(){

			@Override
			public void changedUpdate(DocumentEvent e) 
			{
				updateFilter();
			}

			@Override
			public void insertUpdate(DocumentEvent e) 
			{
				updateFilter();	
			}

			@Override
			public void removeUpdate(DocumentEvent e) 
			{
				updateFilter();	
			}});
		textField.addKeyListener(new KeyListener(){

			@Override
			public void keyPressed(KeyEvent e) {
				if(e.getModifiersEx()==KeyEvent.CTRL_DOWN_MASK && e.getKeyCode()==KeyEvent.VK_SPACE)
				{				
					runBrowser.actionPerformed(new ActionEvent(textField,1,"poka browser"));
				}
				
			}

			@Override
			public void keyReleased(KeyEvent e)
			{}

			@Override
			public void keyTyped(KeyEvent e) {
				
			}});
	}
	
	private void updateFilter()
	{
		bf.setRoot(new FilterLeaf(fieldName,getText()+"*",true));
	}
	
	/**
	 * 
	 * @param lenght - dlugosc text fielda w kolumnach
	 */
	public void setLength(int lenght)
	{
		if((getText()!=null)&&(!getText().equals("")))
		{
			textField.setColumns(lenght);
		}
	}
	
	/**
	 * 
	 * @return dlugosc text fielda w kolumnach
	 */
	public int getLength()
	{
		return textField.getColumns();
	}		
	public String getText()
	{
		return textField.getText();
	}
	public void setText(String test) throws AttribNotFound, UndefineKeyType, SQLException, AliasNotFound
	{
		textField.setText(test);
		updateLinkedFields(test);
	}
	
	private void updateLinkedFields(String keyVal) throws AttribNotFound, UndefineKeyType, SQLException, AliasNotFound 
	{
		if(keyVal==null || keyVal.equals(""))
			return;
		Map<String,String> keyMap = new LinkedHashMap<String, String>();
		keyMap.put(tableManager.getAlias(fieldName), keyVal);
		Map<String, String> record;
		record = tableManager.getRecord(keyMap);
	
		String[] linkedFieldsKeys = linkedFields.keySet().toArray(new String[0]);
		for(int i=0;i<linkedFieldsKeys.length;++i)
		{
			String key = linkedFieldsKeys[i];
			linkedFields.get(key).getComponent().setText(record.get(key));
		}		
	}

	private void addBasicButtonAction()
	{				
		bf = new BrowserFilter();
		String fieldVal = getText();
		bf.setRoot(new FilterLeaf(fieldName,fieldVal,true));
		runBrowser.setBrowserFilter(bf);
		showVocButton.removeActionListener(runBrowser);
		runBrowser.setTableName(tableName);		
		runBrowser.setModal(true);
		runBrowser.addKeyListenerToBrowser(new KeyListener(){

			@Override
			public void keyPressed(KeyEvent e) 
			{
				if(e.getKeyCode()==KeyEvent.VK_ENTER)
				{
					insertValIntoTextField(runBrowser.getBrowser().getSelectedRecord());
					runBrowser.disposeBrowser();
				}
			}

			@Override
			public void keyReleased(KeyEvent e) 
			{}

			@Override
			public void keyTyped(KeyEvent e) 
			{}
			
		});
		runBrowser.addMouseListenerToBrowser(new MouseListener(){

			@Override
			public void mouseClicked(MouseEvent e) 
			{
				if(e.getButton()==MouseEvent.BUTTON1 && e.getClickCount()==2)
				{
					insertValIntoTextField(runBrowser.getBrowser().getSelectedRecord());
					runBrowser.disposeBrowser();
				}
			}

			@Override
			public void mouseEntered(MouseEvent e) 
			{}		
			@Override
			public void mouseExited(MouseEvent e) 
			{}
			@Override
			public void mousePressed(MouseEvent e) 
			{}
			@Override
			public void mouseReleased(MouseEvent e) 
			{}
			
		});
		runBrowser.setSize( new Dimension(200,200));		
		showVocButton.addActionListener(runBrowser); //TODO dorobic,zeby sie modalnie wyswietlalo	
	}

	protected void insertValIntoTextField(Map<String, String> selectedRecord)
	{		
			try {
				setText(
						tableManager.getRecord(selectedRecord).get(fieldName)
						);		
			} catch (Exception e) 
			{
				Application.getInstance().notifyAboutException(e);
			}		
	}
	public void setEnabled(boolean editable)
	{
		textField.setEnabled(editable);
		showVocButton.setEnabled(editable);
	}	

	public void addLinkedField(LinkedField linkedField) throws SuchComponentExictException 
	{
		if(linkedFields.get(linkedField.getFieldName())!=null)
			throw new SuchComponentExictException(linkedField.getFieldName());
		linkedField.getComponent().setEnabled(false);
		linkedFields.put(linkedField.getFieldName(), linkedField);		
	}	
	public void setEnableForLinkedComponents(boolean enable)
	{
		String[] keys = linkedFields.keySet().toArray(new String[0]); 
		for(int i=0;i<keys.length;++i)
		{
			linkedFields.get(keys[i]).getComponent().setEnabled(enable);
		}
	}

	public void includeLinkedFields(Map<String, String> record)
	{
		String[] keys = linkedFields.keySet().toArray(new String[0]);
		for(int i=0;i<keys.length;++i)
		{
			String key = keys[i];
			if(record.get(key)!=null&&!record.get(key).equals(""))
				Application.getInstance().notifyAboutException(new SuchComponentExictException(key));
			record.put(key,linkedFields.get(key).getText());
		}
	}

	public void setLinkedFields(Map<String, String> record) 
	{
		String[] keys = linkedFields.keySet().toArray(new String[0]);
		for(int i=0;i<keys.length;++i)
		{
			String key = keys[i];
			String val = record.get(key);
			linkedFields.get(key).setText(val);
		}
	}
}
